
  function discover(acct, f) {
    getXRD(getHostMetaURL(acct), function(hostMeta) {
      var lrddLink = hostMeta.getByRel('lrdd');
      var lrddTemplate = lrddLink.attributes['template'].value;
      var lrddURL = lrddTemplate.replace('{uri}', acct);
      getXRD(lrddURL, function(lrddXRD) {
         f(lrddXRD);
      });
    });
  };
  
  /* ---------- XHR */
  function getXRD(uri, callback) {
    _xhr = new XMLHttpRequest();
    _xhr.open("GET", uri, true);
    _xhr.onreadystatechange = function() {
      if ( _xhr.readyState != 4 )  { return; }
      var xrd = new XRD(_xhr.responseText);
      callback(xrd);
      return;
    };
    _xhr.send(null);
  }
  
  function getHostMetaURL(webfinger) {
    var acctRegEx = /^acct:(.*$)/;
    if (acctRegEx.test(webfinger)) {
      lastAt = webfinger.lastIndexOf('@');
      if (-1 != lastAt) {
        domain = webfinger.substring(lastAt + 1);
      }
    } else {
      alert('Only handling acct: uris right now!. ' + webfinger);
    }
    return 'http://' + domain + '/.well-known/host-meta';
  }
  
  var XRD = function(xrdText) {
    parser = new DOMParser();
    this.xmlDoc = parser.parseFromString(xrdText,"text/xml");
  };
  
  /* ---------- Parsing functions */
  
  XRD.prototype.getSubject = function() {
    //get the subject
  };
  
  XRD.prototype.getAliases = function() {
    //get the aliases
  };
  
  XRD.prototype.getByRel = function(rel) {
    var all = this.getAllByRel(rel);
    if (all.length > 0) {
        return all[0];
    }
    return null;
  };

  XRD.prototype.getAllByRel = function (rel) {
    var links = this.xmlDoc.getElementsByTagName('Link');
    var arr = [];
    for (var x = 0; x < links.length; x++) {
      var link = links[x];
      for (var y = 0; y < link.attributes.length; y++) {
        if (link.attributes[y].name == 'rel' && link.attributes[y].value == rel) {
          arr.push(link);
          break;
        }
      }
    }
    return arr;
  };
